import wx
import wx.adv
import sys
import time
import base64
from io import BytesIO
import wx.richtext
import socket
import asyncio
import websockets
from threading import Thread
from multiprocessing import Queue


import images
import server_main


class mylog(Thread):
    def __init__(self,window):
        Thread.__init__(self)
        self.window = window

    def run(self):
        while True:
            dic = self.window.queue.get(True)
            if dic['type'] == "close":
                break
            elif dic['type'] == "log":
                wx.CallAfter(self.window.my_logtxt,dic['msg'])


class websockets_server(Thread):
    def __init__(self,window,IP,port):
        Thread.__init__(self)
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)
        self.server = websockets.serve(server_main.run, IP, port, ping_interval=None,loop=self.loop)
        self.window = window

    def run(self):
        self.loop.run_until_complete(self.server)
        self.loop.run_forever()

    def mystop(self):
        print("loop:",self.loop.is_running(),"server:",self.server.ws_server.is_serving(),"server loop:",self.server.ws_server.loop.is_running())

        def run_close(server,loop):
            asyncio.ensure_future(server.close_task,loop=loop)

        if self.loop.is_running():
            if self.server.ws_server.is_serving():
                self.server.ws_server.close()
                time.sleep(0.5)
                if not self.server.ws_server.close_task:
                    self.mystop()
                self.loop.call_soon_threadsafe(run_close,self.server.ws_server,self.loop)
                time.sleep(1)
                if self.server.ws_server.is_serving():
                    self.mystop()
            time.sleep(0.3)
            self.loop.call_soon_threadsafe(self.loop.stop)
            self.loop.call_soon_threadsafe(self.loop.close)
            time.sleep(0.2)
        if self.loop.is_running():
            self.mystop()
        print("loop:",self.loop.is_running(),"server:",self.server.ws_server.is_serving(),"server loop:",self.server.ws_server.loop.is_running())
        server_main.model_dict = {}
        server_main.game_dict = {}
        server_main.root_members = {"members":set(),"root":set()}
        wx.CallAfter(self.window.on_server,None,3)


class MyFrame1(wx.Frame):
    def __init__(self,parent,queue):
        wx.Frame.__init__(self, parent, title = "服务", size = wx.Size( 590,350 ), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER|wx.MAXIMIZE_BOX))
        self._server = None
        self.queue = queue
        server_main.my_queue.update({'log':self.queue})

        wx.StaticLine(self, pos=(90,5), size=(493,2),style=wx.LI_HORIZONTAL)
        wx.StaticLine(self, pos=(90,90), size=(493,2),style=wx.LI_HORIZONTAL)
        wx.StaticLine(self, pos=(92,46), size=(489,2),style=wx.LI_HORIZONTAL)
        wx.StaticLine(self, pos=(90,8), size=(2,82),style=wx.LI_VERTICAL)
        wx.StaticLine(self, pos=(580,8), size=(2,82),style=wx.LI_VERTICAL)
        self.m_button1 = wx.Button( self, label=u"启动服务器", pos=(95,10),size = (70,30))
        self.m_button2 = wx.Button( self, label=u"退出", pos=(505,10),size = (70,30))
        wx.StaticText( self, label=u"黑名单", pos=(240,60))
        self.m_textCtrl1 = wx.TextCtrl( self, value=u"", pos=(280,55),size = (100,28))
        wx.StaticText( self, label=u"黑名单", pos=(385,60),size = (50,30))
        wx.StaticText( self, label=u"端口", pos=(250,15))
        self.m_textCtrl2 = wx.TextCtrl( self, value=u"9001", pos=(280,10),size = (100,28))
        wx.StaticText( self, label=u"端口", pos=(385,15))
        self.m_button3 = wx.Button( self, label=u"添加黑名单", pos=(95,55),size = (70,30))
        self.m_button4 = wx.Button( self, label=u"移除黑名单", pos=(505,55),size = (70,30))
        self.list_goods = wx.ListCtrl(self,style=wx.LC_REPORT,pos=(5,5),size = (80,312))
        self.list_goods.InsertColumn(0, "黑名单用户")

        self.wxlog = wx.richtext.RichTextCtrl(self, value="登录时间：" + time.strftime("%Y-%m-%d %H:%M:%S "), pos=(95,100),size=(480,215))
        self.wxlog.SetStyle(0,30,wx.TextAttr("red","green"))
        self.wxlog.SetDefaultStyle(wx.TextAttr("red","green"))
        FolderBookmarkTaskBarIcon(self)
        self.Layout()
        self.Centre(wx.BOTH)
        self.m_button3.Bind(wx.EVT_BUTTON,self.adduser)
        self.m_button4.Bind(wx.EVT_BUTTON,self.deluser)
        self.m_button1.Bind(wx.EVT_BUTTON, lambda evt, mark=1 : self.on_server(evt,mark))
        self.m_button2.Bind(wx.EVT_BUTTON, lambda evt, mark=2 : self.on_server(evt,mark))
        self.Bind(wx.EVT_CLOSE, lambda evt, mark=1 : self.on_cloase(evt,mark))
        self.Bind(wx.EVT_ICONIZE, lambda evt, mark=2 : self.on_cloase(evt,mark))

        mylog(self).start()

    def on_cloase(self,eve,mak):
        if mak == 1:
            self.Show(False)
        elif mak == 2:
            if eve.GetId() == 1:
                self.Maximize(False)

    def on_server(self,eve,mak):
        if mak == 1:
            self.m_button1.Enable(False)
            try:
                port = self.m_textCtrl2.GetValue()
                port = int(port)
            except ValueError:
                port = 9001
            IP = socket.gethostbyname(socket.gethostname())
            self._server = websockets_server(self,IP, port)
            self._server.start()
            self.SetTitle(IP+":"+str(port))
            self.m_button1.SetLabel("服务运行中")
            self.m_button2.SetLabel("关闭服务器")

        elif mak == 2:
            if self.m_button2.GetLabel() == "退出":
                ret = wx.MessageBox("确定退出吗？", "提示",wx.YES_NO, self)
                if ret == wx.YES:
                    self.queue.put({"type":"close"})
                    self.Destroy()
                    wx.Exit()
                    sys.exit()
            else:
                self.m_button2.Enable(False)
                self.m_button2.SetLabel("关闭中")
                Thread(target=self._server.mystop).start()
            
        elif mak == 3:
            self.m_button1.Enable(True)
            self.m_button2.Enable(True)
            self.SetTitle("服务")
            self.m_button1.SetLabel("启动服务器")
            self.m_button2.SetLabel("退出")

    def adduser( self, eve ):
        txt = self.m_textCtrl1.GetValue()
        if txt:
            if txt not in server_main.my_queue['members']:
                self.list_goods.Append((txt,))
            server_main.my_queue['members'].add(txt)
        self.m_textCtrl1.SetValue("")


    def deluser( self, eve ):
        txt = self.m_textCtrl1.GetValue()
        goodssum = self.list_goods.GetItemCount()
        for i in range(0,goodssum):
            m = i - (goodssum - self.list_goods.GetItemCount())
            if txt:
                if txt == self.list_goods.GetItemText(m):
                    if self.list_goods.GetItemText(m) in server_main.my_queue['members']:
                        server_main.my_queue['members'].remove(self.list_goods.GetItemText(m))
                    self.list_goods.DeleteItem(m)
            elif self.list_goods.IsSelected(m):
                if self.list_goods.GetItemText(m) in server_main.my_queue['members']:
                    server_main.my_queue['members'].remove(self.list_goods.GetItemText(m))
                self.list_goods.DeleteItem(m)
        self.m_textCtrl1.SetValue("")

    def my_logtxt(self,txt):
        self.wxlog.AddParagraph(txt)
        self.wxlog.AppendText(" ")
        self.wxlog.ShowPosition(-1)



class FolderBookmarkTaskBarIcon(wx.adv.TaskBarIcon):
    TITLE = '服务器'

    def __init__(self,windows):
        super().__init__()
        by = BytesIO(base64.b64decode(images.imge))
        p = wx.Image(by, type=wx.BITMAP_TYPE_ICO)
        by.close()
        wxico = wx.Icon()
        wxico.CopyFromBitmap(wx.Bitmap(p))
        self.SetIcon(wxico, self.TITLE)
        self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.showset)
        self.windows = windows

    def showset(self,eve):
        self.windows.Show(True)
        self.windows.ToggleWindowStyle(wx.STAY_ON_TOP)
        self.windows.ToggleWindowStyle(wx.STAY_ON_TOP)
        self.windows.GetEventHandler().ProcessEvent(wx.IconizeEvent(id=1, iconized=False))

#wx_app = wx.App()
#MyFrame1(None,Queue()).Show(True)
#wx_app.MainLoop()

